#include "Vertex.h"

#include <sstream>
#include <iomanip>

#include <cmath>

using std::stringstream;

Vertex::Vertex():
		m_x(0.0f), m_y(0.0f), m_z(0.0f), m_w(1.0f)
{
}

Vertex::Vertex(float x, float y, float z, float w):
		m_x(x), m_y(y), m_z(z), m_w(w)
{
}

Vertex::Vertex(const Vertex& other):
		m_x(other.m_x), m_y(other.m_y), m_z(other.m_z)
{
}

Vertex::~Vertex()
{
}


Vertex& Vertex::operator = (const Vertex& other)
{
	m_x = other.m_x;
	m_y = other.m_y;
	m_z = other.m_z;
	
	return *this;
}

Vertex& Vertex::operator += (const Vertex& other)
{
	m_x += other.m_x;
	m_y += other.m_y;
	m_z += other.m_z;
	
	return *this;
}

Vertex& Vertex::operator -= (const Vertex& other)
{
	m_x -= other.m_x;
	m_y -= other.m_y;
	m_z -= other.m_z;
	
	return *this;
}

Vertex Vertex::operator + (const Vertex& other) const
{
	Vertex tmp(m_x + other.m_x, m_y + other.m_y, m_z + other.m_z);
	return tmp;
}

Vertex Vertex::operator - (const Vertex& other) const
{
	Vertex tmp(m_x - other.m_x, m_y - other.m_y, m_z - other.m_z);
	return tmp;
}

float Vertex::operator * (const Vertex& other) const
{
	return m_x * other.m_x  +  m_y * other.m_y  +  m_z * other.m_z;
}

Vertex Vertex::operator ^(const Vertex& other) const
{
	Vertex tmp(
	    m_y * other.m_z  -  m_z * other.m_y,
	    m_z * other.m_x  -  m_x * other.m_z,
	    m_x * other.m_y  -  m_y * other.m_x
	);
	
	return tmp;
}


float Vertex::getX() const
{
	return m_x;
}

float Vertex::getY() const
{
	return m_y;
}

float Vertex::getZ() const
{
	return m_z;
}

void Vertex::getXZ(float& x, float& z) const
{
	x = m_x;
	z = m_z;
}

void Vertex::getAll(float& x, float& y, float& z) const
{
	x = m_x;
	y = m_y;
	z = m_z;
}

void Vertex::getAll(float& x, float& y, float& z, float& w) const
{
	x = m_x;
	y = m_y;
	z = m_z;
	w = m_w;
}

void Vertex::setX(float x)
{
	m_x = x;
}

void Vertex::setY(float y)
{
	m_y = y;
}

void Vertex::setZ(float z)
{
	m_z = z;
}

void Vertex::setAll(const Vertex& other)
{
	m_x = other.m_x;
	m_y = other.m_y;
	m_z = other.m_z;
}

void Vertex::setAll(float x, float y, float z)
{
	m_x = x;
	m_y = y;
	m_z = z;
}

Vertex& Vertex::normalize()
{
	float d = sqrt(m_x * m_x + m_y * m_y + m_z * m_z);
	if (d < 0.0000001f)
	{
		d = 1.0f;
	}
	
	m_x /= d;
	m_y /= d;
	m_z /= d;
	
	return *this;
}

void Vertex::draw_v() const
{
	glVertex3f(m_x, m_y, m_z);
}

void Vertex::draw_n() const
{
	glNormal3f(m_x, m_y, m_z);
}

string Vertex::toString() const
{
	stringstream ss;
	ss << std::setprecision(6) << std::fixed << m_x << " " << m_y << " " << m_z;
	
	return ss.str();
}

